package org.uni_hi.lsep.util;

import java.util.Vector;

import org.uni_hi.lsep.gui.util.PacketData;
import org.uni_hi.lsep.gui.util.PacketData.Protocol;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

public class DataPacket extends Vector<Object>{

	/**
	 * 
	 */
	private static final long serialVersionUID = 4199843211091927031L;

	public enum DataPosition{FW_IP,SRC_IP,DST_IP,PROTO,OPT_DAT1,OPT_DAT2,ACTION,TEXT}; 
	
	public DataPacket(){
		this(null,null,null,null,null,null,null,null);
	}
	
	public DataPacket (IPAddress fwIP, IPAddress srcIP, IPAddress dstIP, PacketData.Protocol prot, PacketData.Action act){
		this(fwIP, srcIP, dstIP, prot, null, null, act,null);
	}
	
	public DataPacket (IPAddress fwIP, IPAddress srcIP, IPAddress dstIP, PacketData.Protocol prot, OptionalDataIF opt1, OptionalDataIF opt2, PacketData.Action act,TextData text){
		super(DataPosition.values().length);
		add(DataPosition.FW_IP.ordinal(), fwIP);
		add(DataPosition.SRC_IP.ordinal(),srcIP);
		add(DataPosition.DST_IP.ordinal(),dstIP);
		add(DataPosition.PROTO.ordinal(),prot);
		add(DataPosition.OPT_DAT1.ordinal(),opt1);
		add(DataPosition.OPT_DAT2.ordinal(),opt2);
		add(DataPosition.ACTION.ordinal(),act);
		add(DataPosition.TEXT.ordinal(),text);
	}
	
	public Element setElementData(Element e){
		OptionalDataIF od=null;
		for(Object o:elementData){
			od=(OptionalDataIF)o;
			if(od!=null){
				e.setAttribute(od.getAttributeName(), od.toString());
			}
		}
		return e;
	}
	
	public void add(int pos, OptionalDataIF obj){
		while(size()<pos){
			super.add(null);
		}
		super.add(pos, obj);
	}
	
	public void setParsedFirewallIP(String ip) throws IPAddressSyntaxException{
		set(DataPosition.FW_IP.ordinal(),IPAddress.parse(ip,FileManager.FW_IP_ATT));
	}
	
	public void setParsedSourceIP(String ip) throws IPAddressSyntaxException{
		set(DataPosition.SRC_IP.ordinal(),IPAddress.parse(ip,FileManager.SRC_IP_ATT));
	}
	
	public void setParsedDestinationIP(String ip) throws IPAddressSyntaxException{
		set(DataPosition.DST_IP.ordinal(),IPAddress.parse(ip,FileManager.DST_IP_ATT));
	}
	
	public void setFirewallIP(IPAddress ip){
		ip.setAttributeName(FileManager.FW_IP_ATT);
		set(DataPosition.FW_IP.ordinal(),ip);
	}
	
	public void setSourceIP(IPAddress ip){
		ip.setAttributeName(FileManager.SRC_IP_ATT);
		set(DataPosition.SRC_IP.ordinal(),ip);
	}
	
	public void setDestinationIP(IPAddress ip){
		ip.setAttributeName(FileManager.DST_IP_ATT);
		set(DataPosition.DST_IP.ordinal(),ip);
	}
	
	public void setProtocol(PacketData.Protocol prot){
		set(DataPosition.PROTO.ordinal(),prot);
	}
	
	public void setDescription(TextData description){
		set(DataPosition.TEXT.ordinal(),description);
	}
		
	public void setSrcPort(PortAddress port){
		port.setAttributeName(FileManager.SRC_PORT_ATT);
		setOptionalData1(port);
	}
	
	public void setDstPort(PortAddress port){
		port.setAttributeName(FileManager.DST_PORT_ATT);
		setOptionalData2(port);
	}
	
	public void setOptionalData1(OptionalDataIF d){
		set(DataPosition.OPT_DAT1.ordinal(),d);
	}
	
	public void setOptionalData2(OptionalDataIF d){
		set(DataPosition.OPT_DAT2.ordinal(),d);
	}
	
	public void setAction(PacketData.Action action){
		set(DataPosition.ACTION.ordinal(),action);
	}
	
	public void setName(TextData name){
		set(DataPosition.TEXT.ordinal(),name);
	}
	
	public IPAddress getFirewallIP(){
		return (IPAddress)get(DataPosition.FW_IP.ordinal());
	}
	
	public IPAddress getSourceIP(){
		return (IPAddress)get(DataPosition.SRC_IP.ordinal());
	}
	
	public IPAddress getDestinationIP(){
		return (IPAddress)get(DataPosition.DST_IP.ordinal());
	}
	
	public PacketData.Protocol getProtocol(){
		return (PacketData.Protocol) get(DataPosition.PROTO.ordinal());
	}
	
	public PacketData.ICMP_Type getICMPType(){
		return (PacketData.ICMP_Type) getOptionalData1();
	}
	
	public PacketData.ICMP_Code getICMPCode(){
		return (PacketData.ICMP_Code) getOptionalData2();
	}
	
	public PortAddress getSourcePort(){
		return (PortAddress) getOptionalData1();
	}
	
	public PortAddress getDestinationPort(){
		return (PortAddress) getOptionalData2();
	}
	
	public OptionalDataIF getOptionalData1(){
		return (OptionalDataIF) get(DataPosition.OPT_DAT1.ordinal());
	}
	
	public OptionalDataIF getOptionalData2(){
		return (OptionalDataIF) get(DataPosition.OPT_DAT2.ordinal());
	}
	
	public PacketData.Action getAction(){
		return (PacketData.Action) get(DataPosition.ACTION.ordinal());
	}
	
	public TextData getDescription(){
		return (TextData) get(DataPosition.TEXT.ordinal());
	}
	
	public TextData getName(){
		return (TextData) get(DataPosition.TEXT.ordinal());
	}
	
	public String toString(){
		String result="\t"+getDescription()+"  ["+getAction().getLogString()+"]\n"+
			"\t"+getFirewallIP().getLogString()+", "+getSourceIP().getLogString()+", "+getDestinationIP().getLogString()+", \n"+
			"\t"+getProtocol().getLogString();
		if(!getProtocol().equals(PacketData.Protocol.IP)){
			result+=", "+getOptionalData1().getLogString()+", "+getOptionalData2().getLogString();
		}
		return result;
	}
	
	public static DataPacket parseNode(Node n) throws DOMException, PortAddressSyntaxException, IPAddressSyntaxException{
		DataPacket dp=new DataPacket();
		dp.setParsedName(n.getAttributes().getNamedItem(FileManager.NAME_ATT).getNodeValue());
		dp.setParsedAction(n.getAttributes().getNamedItem(FileManager.ACTION_ATT).getNodeValue());
		
		dp.setParsedProtocol(n.getAttributes().getNamedItem("protocol").getNodeValue());
		
		dp.setParsedFirewallIP(n.getAttributes().getNamedItem(FileManager.FW_IP_ATT).getNodeValue());
		
		dp.setParsedSourceIP(n.getAttributes().getNamedItem(FileManager.SRC_IP_ATT).getNodeValue());
		
		dp.setParsedDestinationIP(n.getAttributes().getNamedItem(FileManager.DST_IP_ATT).getNodeValue());

		if (dp.getProtocol().ordinal()>=Protocol.TCP.ordinal()) {
				dp.setParsedSourcePort(n.getAttributes().getNamedItem(FileManager.SRC_PORT_ATT).getNodeValue());
				dp.setParsedDestiationPort(n.getAttributes().getNamedItem(FileManager.DST_PORT_ATT).getNodeValue());
		}else if (dp.getProtocol().equals(Protocol.ICMP)) {
			dp.setParsedICMPType(n.getAttributes().getNamedItem(FileManager.ICMP_TYPE_ATT).getNodeValue());
			dp.setParsedICMPCode(n.getAttributes().getNamedItem(FileManager.ICMP_CODE_ATT).getNodeValue());
		}
		return dp;
	}

	public void setParsedICMPCode(String nodeValue) {
		setICMPCode(PacketData.ICMP_Code.valueOf(nodeValue));
	}

	public void setICMPCode(PacketData.ICMP_Code valueOf) {
		setOptionalData2(valueOf);
	}

	public void setParsedICMPType(String nodeValue) {
		setICMPType(PacketData.ICMP_Type.valueOf(nodeValue));
	}

	public void setICMPType(PacketData.ICMP_Type valueOf) {
		setOptionalData1(valueOf);
	}

	public void setParsedDestiationPort(String nodeValue) throws PortAddressSyntaxException {
		setDstPort(PortAddress.parse(nodeValue, FileManager.DST_PORT_ATT));
	}

	public void setParsedSourcePort(String nodeValue) throws PortAddressSyntaxException {
		setSrcPort(PortAddress.parse(nodeValue, FileManager.SRC_PORT_ATT));
	}

	public void setParsedProtocol(String nodeValue) {
		setProtocol(PacketData.Protocol.valueOf(nodeValue));
	}

	public void setParsedAction(String valueOf) {
		setAction(PacketData.Action.valueOf(valueOf));
	}

	public void setParsedName(String nodeValue) {
		setName(new TextData(nodeValue,FileManager.NAME_ATT));
	}
	
	public OptionalDataIF get(int index){
		return (OptionalDataIF) super.get(index);
	}
}